#include<cmath>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=10005;
int f[M],rank[M],ans[M],deg[M],res[M];//ans答案,deg表示各点的入度 
bool vis[M];
int n;
int bg,ed;
vector<int> v[M],que[M];//v存放邻接表,que存放询问 
void makeset()
{
	for(int i=1;i<=n;i++)
	{
		f[i]=i;
		rank[i]=0;
	}
}
int find(int i)
{
    int k,t,j=i;
    while(f[j]!=j)j=f[j];
    for(k=i;f[k]!=k;)
    {
      t=k;
      k=f[k];
      f[t]=j;
      }
    return j;
}

void unionset(int a,int b)
{
	a=find(a);
	b=find(b);
    if(rank[a]<rank[b])
       f[a]=b;
	else
	{
	f[b]=a;
	  if(rank[a]==rank[b])
      rank[a]++;
	}
}//并查集 
void lca(int x) 
{
	ans[x]=x;//开始时将当前节点的祖先节点设为其本身 
	int size=v[x].size();
	for(int i=0;i<size;i++)
	{
		lca(v[x][i]);//依次遍历当前节点的子树 
		unionset(x,v[x][i]);
		ans[find(x)]=x;//将当前点设为该集合的祖先节点 
	}
	vis[x]=1;//标记该点已被访问 
	size=que[x].size();//存在从当前点x到que[x][i]的询问 
	for(int i=0;i<size;i++)
	{
		if(vis[que[x][i]])//que[x][i]也已被访问 
		{
			//printf("%d\n",ans[find(que[x][i])]);
			res[ans[find(que[x][i])]]++;
		}
	}
}
int main()
{
	freopen("test.in","r",stdin);
	while(scanf("%d",&n)!=EOF)
	{
		memset(f,0,sizeof(f));
		memset(rank,0,sizeof(rank));
		memset(deg,0,sizeof(deg));
		memset(vis,0,sizeof(vis));
		for(int i=0;i<M;i++)
		{
			v[i].clear();
			que[i].clear();
		}
		makeset();
		int nn,s,e;
		for(int i=0;i<n;i++)
		{
			scanf("%d:(%d)",&s,&nn);
			for(int k=0;k<nn;k++)
			{
				scanf("%d",&e);
				v[s].push_back(e);//构造邻接表,有向图 
				deg[e]++;//点ed的入度加1 
			}
		}
		int m;
		scanf("%d",&m);
		for(int i=1;i<=m;i++)
		{
			while(getchar()!='(');
			scanf("%d%d",&bg,&ed);
		//	printf("%d %d\n",bg,ed);
			que[bg].push_back(ed);//询问要双向构造 
			que[ed].push_back(bg);
			while(getchar()!=')');
		}
		memset(res,0,sizeof(res));
		for(int i=1;i<=n;i++)        
			if(!deg[i])//找树根(入度为0) 
			{
				lca(i);//递归调用lca 
				break;
			}
		for(int i=1;i<=n;i++)
			if(res[i]!=0)printf("%d:%d\n",i,res[i]);
	}
	//system("pause");
	return 0;
}
